import sys
import os
import json
import subprocess
from PyQt5.QtWidgets import (
    QApplication, QWidget, QPushButton, QFileDialog, QLabel,
    QVBoxLayout, QTextEdit, QLineEdit, QHBoxLayout, QMessageBox
)

class RPMToDebConverter(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("RPM to DEB 转换工具")
        self.dependency_mapping = self.load_dependency_mapping()
        self.initUI()
        self.check_dependencies()

    def load_dependency_mapping(self):
        """加载预设的 RPM 到 DEB 依赖项映射"""
        mapping_path = os.path.join(os.path.dirname(__file__), "rpm-to-deb-deps.json")
        try:
            with open(mapping_path, "r") as f:
                return json.load(f)
        except FileNotFoundError:
            QMessageBox.warning(
                self, "警告", 
                f"未找到依赖项映射文件 '{mapping_path}'，将使用默认映射。"
            )
            return {
                "libstdc++.so.6": "libstdc++6",
                "glibc": "libc6",
                "zlib": "zlib1g",
                "libX11.so.6": "libx11-6"
            }
        except json.JSONDecodeError:
            QMessageBox.critical(
                self, "错误", 
                "依赖项映射文件格式错误，请检查 JSON 格式。"
            )
            sys.exit(1)

    def map_rpm_to_deb_dep(self, dep):
        """根据映射规则替换依赖项名称"""
        return self.dependency_mapping.get(dep, dep)

    def initUI(self):
        layout = QVBoxLayout()

        # 1. 文件选择
        file_layout = QHBoxLayout()
        self.file_label = QLabel("未选择文件")
        self.select_btn = QPushButton("选择 RPM 文件")
        self.select_btn.clicked.connect(self.select_rpm_file)
        file_layout.addWidget(self.file_label)
        file_layout.addWidget(self.select_btn)
        layout.addLayout(file_layout)

        # 2. 元数据输入
        self.name_input = self.create_input("包名")
        self.version_input = self.create_input("版本号")
        self.depends_input = self.create_text_input("依赖项（逗号分隔）")
        self.description_input = self.create_text_input("描述")

        layout.addWidget(QLabel("包名:"))
        layout.addWidget(self.name_input)
        layout.addWidget(QLabel("版本号:"))
        layout.addWidget(self.version_input)
        layout.addWidget(QLabel("依赖项:"))
        layout.addWidget(self.depends_input)
        layout.addWidget(QLabel("描述:"))
        layout.addWidget(self.description_input)

        # 3. 自动填充按钮
        self.auto_fill_btn = QPushButton("自动填充元数据")
        self.auto_fill_btn.clicked.connect(self.auto_fill_metadata)
        layout.addWidget(self.auto_fill_btn)

        # 4. 转换按钮
        self.convert_btn = QPushButton("开始转换")
        self.convert_btn.clicked.connect(self.convert_to_deb)
        layout.addWidget(self.convert_btn)

        # 5. 日志输出
        self.log = QTextEdit()
        self.log.setReadOnly(True)
        layout.addWidget(QLabel("日志:"))
        layout.addWidget(self.log)

        self.setLayout(layout)

    def create_input(self, placeholder):
        input_field = QLineEdit()
        input_field.setPlaceholderText(placeholder)
        return input_field

    def create_text_input(self, placeholder):
        input_field = QTextEdit()
        input_field.setPlaceholderText(placeholder)
        return input_field

    def check_dependencies(self):
        """检查系统是否安装 fpm 和 rpm 工具"""
        try:
            subprocess.run(["which", "fpm"], capture_output=True, check=True)
            subprocess.run(["which", "rpm"], capture_output=True, check=True)
        except subprocess.CalledProcessError:
            QMessageBox.critical(
                self, "错误", 
                "未找到必要的工具！请先安装 fpm 和 rpm。\n"
                "安装方法（Ubuntu/Debian）:\n"
                "1. 安装 Ruby: sudo apt install ruby ruby-dev build-essential\n"
                "2. 安装 fpm: sudo gem install fpm\n"
                "3. 安装 rpm: sudo apt install rpm"
            )
            sys.exit(1)

    def select_rpm_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "选择 RPM 文件", "", "RPM 文件 (*.rpm)")
        if file_path:
            self.file_label.setText(file_path)

    def extract_rpm_metadata(self, rpm_path):
        """提取 RPM 包的元数据"""
        meta = {
            "name": "",
            "version": "",
            "depends": [],
            "description": ""
        }

        try:
            # 提取名称、版本
            cmd = ["rpm", "-qpi", rpm_path]
            result = subprocess.run(cmd, capture_output=True, text=True, check=True)
            for line in result.stdout.splitlines():
                if line.startswith("Name        :"):
                    meta["name"] = line.split(":")[1].strip()
                elif line.startswith("Version     :"):
                    meta["version"] = line.split(":")[1].strip()

            # 提取依赖项
            cmd = ["rpm", "-qRp", rpm_path]
            result = subprocess.run(cmd, capture_output=True, text=True, check=True)
            meta["depends"] = [
                self.map_rpm_to_deb_dep(dep.strip()) 
                for dep in result.stdout.splitlines()
            ]

            # 提取描述
            description_started = False
            for line in result.stdout.splitlines():
                if line.startswith("Summary(:|$)"):
                    description_started = True
                    continue
                if description_started and line.strip():
                    meta["description"] += line.strip() + " "
                if description_started and not line.strip():
                    break
        except subprocess.CalledProcessError as e:
            self.log.append(f"元数据提取失败: {e.stderr}")
            return meta

        return meta

    def auto_fill_metadata(self):
        rpm_path = self.file_label.text()
        if not rpm_path or rpm_path == "未选择文件":
            self.log.append("请先选择一个 RPM 文件！")
            return

        meta = self.extract_rpm_metadata(rpm_path)
        if meta["name"]:
            self.name_input.setText(meta["name"])
            self.version_input.setText(meta["version"])
            self.depends_input.setPlainText(", ".join(meta["depends"]))
            self.description_input.setPlainText(meta["description"])
            self.log.append("元数据已自动填充（依赖项已映射）！")
        else:
            self.log.append("元数据提取失败，请手动填写。")

    def convert_to_deb(self):
        rpm_path = self.file_label.text()
        if not rpm_path or rpm_path == "未选择文件":
            self.log.append("请先选择一个 RPM 文件！")
            return

        package_name = self.name_input.text()
        version = self.version_input.text()
        depends = [self.map_rpm_to_deb_dep(d.strip()) for d in self.depends_input.toPlainText().split(",")]
        description = self.description_input.toPlainText()

        if not package_name or not version:
            self.log.append("包名和版本号不能为空！")
            return

        # 构建 FPM 命令
        command = [
            "fpm",
            "-s", "rpm", "-t", "deb",
            "--name", package_name,
            "--version", version,
            "--description", description,
            "--maintainer", "Your Name <your@email.com>",
            "--license", "GPLv3",
            "--url", "https://example.com"
        ]

        # 添加依赖项
        for dep in depends:
            if dep:
                command.extend(["--depends", dep])

        # 添加输入文件
        command.append(rpm_path)

        self.log.append("开始转换...命令: " + " ".join(command))
        try:
            result = subprocess.run(command, capture_output=True, text=True, check=True)
            self.log.append("转换成功！")
            self.log.append(result.stdout)
            QMessageBox.information(self, "成功", "DEB 包已生成！")
        except subprocess.CalledProcessError as e:
            self.log.append("转换失败！")
            self.log.append(e.stderr)
            QMessageBox.critical(self, "错误", f"转换失败: {e.stderr}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = RPMToDebConverter()
    window.resize(600, 600)
    window.show()
    sys.exit(app.exec_())